package thread.test2Lock;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * 1,synchronized 有缺陷（比如，一锁就锁定整个方法，，比如像读写锁，这样的，
 * 读锁和读锁，不应该互斥）
 *
 * ReentrantLock  是唯一实现了 Lock接口的类
 *
 *
 * 1，通过lock.lock（）获取锁的时候，这个时候的阻塞是不能够中断的，如果，想
 * 能被中断可以通过 lock.lockInterruptibly()的方式获取锁
 *
 * 如果需要正确中断等待锁的线程，必须将获取锁放在外面，
 * 然后将InterruptedException抛出（也就是将lock.lockInterruptibly() 放到，中断异常的try catch外面）
 *
 *
 * 2，ReentrantReadWriteLock  中有 readlock,和writelock, 通过 rwl.readLock().lock()，rwl.readLock().unlock();
 * 等获取和释放锁
 *
 * 3，ReentrantLock和ReentrantReadWriteLock 默认情况下是非公平锁，可以，添加构造函数，参数来指定，
 * 公平还是非公平，而synchrinoze 是非公平锁
 *
 * 4，另外在ReentrantLock类中定义了很多方法，比如：isFair()        //判断锁是否是公平锁
 * isLocked()    //判断锁是否被任何线程获取了
 * isHeldByCurrentThread()   //判断锁是否被当前线程获取了
 * hasQueuedThreads()   //判断是否有线程在等待该锁
 *
 * 在ReentrantReadWriteLock中也有类似的方法，同样也可以设置为公平锁和非公平锁。
 * 不过要记住，ReentrantReadWriteLock并未实现Lock接口，它实现的是ReadWriteLock接口。
 *
 * ##### lock的方法
 * void lock();
 * void lockInterruptibly() throws InterruptedException;
 * boolean tryLock();
 * boolean tryLock(long time, TimeUnit unit) throws InterruptedException;
 * void unlock();
 * Condition newCondition();
 *
 */
public class LockTest1 {
    public static void main(String[] args) {
        //默认非公平锁，可以传入参数true表示公平锁
        final Lock lock=new ReentrantLock();

        //线程1
        new Thread(new Runnable() {
            @Override
            public void run() {
               try{
                   //获取锁，会一直等待
                   lock.lock();
                   for(int i=0;i<100;i++){
                       System.out.println(Thread.currentThread().getName());
                   }

               }catch (Exception e){
                    e.printStackTrace();
               }finally {
                   lock.unlock();
               }
            }
        }).start();


        //线程2
        new Thread(new Runnable() {
            @Override
            public void run() {
                try{
                    //尝试获取锁，获取不到时会返回false;
                    boolean a=lock.tryLock();
                    for(int i=0;i<100;i++){
                        System.out.println(Thread.currentThread().getName());
                    }

                }catch (Exception e){
                    e.printStackTrace();
                }finally {
                    lock.unlock();
                }
            }
        }).start();

        //线程3
        new Thread(new Runnable() {
            @Override
            public void run() {
                try{
                    //尝试获取锁，可以被中断  而用synchronized修饰的话，当一个线程处于等待某个锁的状态，
                    // 是无法被中断的，只有一直等待下去。
                    lock.lockInterruptibly();
                    for(int i=0;i<100;i++){
                        System.out.println(Thread.currentThread().getName());
                    }

                }catch (Exception e){
                    e.printStackTrace();
                }finally {
                    lock.unlock();
                }
            }
        }).start();
    }
}
